using System;
using System.Data;
using System.Collections;
using MicrosoftSQLHelper;
using MicrosoftORACLEHelper;
using MySql.Data.MySqlClient;
using System.IO;
using System.Windows.Forms;

namespace DataAccessArquitectura
{
	
	public class ArquitecturaDB
	{
		#region < VARIABLES >
		private enmTipoBaseDatos mTipoBD;
		private const string mCnnStrSQL		= "";
		private const string mCnnStrORACLE	= "";
        //private const string mCnnStrMySQL = "Database=datavelez2;Data Source=localhost;User Id=root;Password=velez";
        private string mCnnStrMySQL = "";
        private const string mCnnStrACCESS = "";
        #endregion

		#region < CONSTRUCTORES >
		public ArquitecturaDB(enmTipoBaseDatos tipoBD)
		{
			mTipoBD		= tipoBD;
            StreamReader leer = new StreamReader(Application.StartupPath + @"\systemsofter.txt");
            string linea = leer.ReadLine();
            mCnnStrMySQL = linea;
		}
		#endregion

		#region < METODOS PRIVADOS UTILES >
		private string EliminaUltimoCaracter(string dato)
		{
			return dato.Substring(0,dato.Length-1);
		}
		private object EjecutaSqlSegunBD(string sql, enmTipoRetornoEjecucion tiporetorno)
		{
			object r		= null;
			string CnnStr	= "";
			
			switch(mTipoBD)
			{
				case enmTipoBaseDatos.SQL:
					CnnStr = mCnnStrSQL;
					break;
				case enmTipoBaseDatos.Oracle:
					CnnStr = mCnnStrORACLE;
					break;
                case enmTipoBaseDatos.MySQL:
                    CnnStr = mCnnStrMySQL;
                    break;
                case enmTipoBaseDatos.OleDB:
                    CnnStr = mCnnStrACCESS;
                    break;
			}
			
			try
			{
				if(mTipoBD == enmTipoBaseDatos.SQL)
				{
					switch(tiporetorno)
					{
						case enmTipoRetornoEjecucion.DataSet:
							r = SqlHelper.ExecuteDataset(CnnStr,CommandType.Text,sql);
							break;
						case enmTipoRetornoEjecucion.NonQuery:
							r = SqlHelper.ExecuteNonQuery(CnnStr,CommandType.Text,sql);
							break;
						case enmTipoRetornoEjecucion.Reader:
							r = SqlHelper.ExecuteReader(CnnStr,CommandType.Text,sql);
							break;
						case enmTipoRetornoEjecucion.Scalar:
							r = SqlHelper.ExecuteScalar(CnnStr,CommandType.Text,sql);
							break;
					}
				}
				if(mTipoBD == enmTipoBaseDatos.Oracle)
				{
					switch(tiporetorno)
					{
						case enmTipoRetornoEjecucion.DataSet:
							r = OracleHelper.ExecuteDataset(CnnStr,CommandType.Text,sql);
							break;
						case enmTipoRetornoEjecucion.NonQuery:
							r = OracleHelper.ExecuteNonQuery(CnnStr,CommandType.Text,sql);
							break;
						case enmTipoRetornoEjecucion.Reader:
							r = OracleHelper.ExecuteReader(CnnStr,CommandType.Text,sql);
							break;
						case enmTipoRetornoEjecucion.Scalar:
							r = OracleHelper.ExecuteScalar(CnnStr,CommandType.Text,sql);
							break;
					}
				}
                if (mTipoBD == enmTipoBaseDatos.MySQL)
                {
                    switch (tiporetorno)
                    {
                        case enmTipoRetornoEjecucion.DataSet:
                            r = MySqlHelper.ExecuteDataset(CnnStr, sql);
                            break;
                        case enmTipoRetornoEjecucion.NonQuery:
                            r = MySqlHelper.ExecuteNonQuery(CnnStr, sql);
                            break;
                        case enmTipoRetornoEjecucion.Reader:
                            r = MySqlHelper.ExecuteReader(CnnStr, sql);
                            break;
                        case enmTipoRetornoEjecucion.Scalar:
                            r = MySqlHelper.ExecuteScalar(CnnStr,  sql);
                            break;
                    }
                }
                if (mTipoBD == enmTipoBaseDatos.OleDB)
                {
                    // Implementar para Access
                }
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return r;

		}
		private object EjecutaProcedimientoSegunBD(string nombresp, object[] parametros, enmTipoRetornoEjecucion tiporetorno)
		{
			object r		= null;
			string CnnStr	= "";
			
			switch(mTipoBD)
			{
				case enmTipoBaseDatos.SQL:
					CnnStr = mCnnStrSQL;
					break;
				case enmTipoBaseDatos.Oracle:
					CnnStr = mCnnStrORACLE;
					break;
                case enmTipoBaseDatos.MySQL:
                    CnnStr = mCnnStrMySQL;
                    break;
			}
			
			try
			{
				if(mTipoBD == enmTipoBaseDatos.SQL)
				{
					switch(tiporetorno)
					{
						case enmTipoRetornoEjecucion.DataSet:
							r = SqlHelper.ExecuteDataset(CnnStr,nombresp,parametros);
							break;
						case enmTipoRetornoEjecucion.NonQuery:
							r = SqlHelper.ExecuteNonQuery(CnnStr,nombresp,parametros);
							break;
						case enmTipoRetornoEjecucion.Reader:
							r = SqlHelper.ExecuteReader(CnnStr,nombresp,parametros);
							break;
						case enmTipoRetornoEjecucion.Scalar:
							r = SqlHelper.ExecuteScalar(CnnStr,nombresp,parametros);
							break;
					}
				}
				if(mTipoBD == enmTipoBaseDatos.Oracle)
				{
					switch(tiporetorno)
					{
						case enmTipoRetornoEjecucion.DataSet:
							r = OracleHelper.ExecuteDataset(CnnStr,nombresp,parametros);
							break;
						case enmTipoRetornoEjecucion.NonQuery:
							r = OracleHelper.ExecuteNonQuery(CnnStr,nombresp,parametros);
							break;
						case enmTipoRetornoEjecucion.Reader:
							r = OracleHelper.ExecuteReader(CnnStr,nombresp,parametros);
							break;
						case enmTipoRetornoEjecucion.Scalar:
							r = OracleHelper.ExecuteScalar(CnnStr,nombresp,parametros);
							break;
					}
				}
                if (mTipoBD == enmTipoBaseDatos.MySQL)
                {
                    switch (tiporetorno)
                    {
                        case enmTipoRetornoEjecucion.DataSet:
                            r = MySqlHelper.ExecuteDataset(CnnStr, nombresp,(MySqlParameter[]) parametros);
                            break;
                        case enmTipoRetornoEjecucion.NonQuery:
                            r = MySqlHelper.ExecuteNonQuery(CnnStr, nombresp, (MySqlParameter[])parametros);
                            break;
                        case enmTipoRetornoEjecucion.Reader:
                            r = MySqlHelper.ExecuteReader(CnnStr, nombresp, (MySqlParameter[])parametros);
                            break;
                        case enmTipoRetornoEjecucion.Scalar:
                            r = MySqlHelper.ExecuteScalar(CnnStr, nombresp, (MySqlParameter[])parametros);
                            break;
                    }
                } 
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return r;

		}

        private object EjecutaProcedimientoSegunBDMYSQL(string nombresp, MySqlParameter[] parametros, enmTipoRetornoEjecucion tiporetorno)
        {
            object r = null;
            string CnnStr = "";

            switch (mTipoBD)
            {
                case enmTipoBaseDatos.SQL:
                    CnnStr = mCnnStrSQL;
                    break;
                case enmTipoBaseDatos.Oracle:
                    CnnStr = mCnnStrORACLE;
                    break;
                case enmTipoBaseDatos.MySQL:
                    CnnStr = mCnnStrMySQL;
                    break;
            }

            try
            {                
                if (mTipoBD == enmTipoBaseDatos.MySQL)
                {
                    switch (tiporetorno)
                    {
                        case enmTipoRetornoEjecucion.DataSet:
                            r = MySqlHelper.ExecuteDataset(CnnStr, nombresp, parametros);
                            break;
                        case enmTipoRetornoEjecucion.NonQuery:
                            r = MySqlHelper.ExecuteNonQuery(CnnStr, nombresp,parametros);
                            break;
                        case enmTipoRetornoEjecucion.Reader:
                            r = MySqlHelper.ExecuteReader(CnnStr, nombresp, parametros);
                            break;
                        case enmTipoRetornoEjecucion.Scalar:
                            r = MySqlHelper.ExecuteScalar(CnnStr, nombresp, parametros);
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return r;

        }

        private object EjecutaProcedimientoSegunBDMySQL(string sentenciaMySQL, enmTipoRetornoEjecucion tiporetorno)
        {
            object r = null;
            string CnnStr = mCnnStrMySQL;           

            try
            {                                
                if (mTipoBD == enmTipoBaseDatos.MySQL)
                {                    
                    MySqlConnection con = new MySqlConnection(CnnStr);
                    MySqlCommand cmd = new MySqlCommand(sentenciaMySQL, con);
                    cmd.CommandType = CommandType.Text;
                    con.Open();                    
                    r = cmd.ExecuteNonQuery();
                    con.Close();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return r;

        }
      
		#endregion

		#region < METODOS PUBLICOS SELECT >
		public DataSet EjecutarSelectDs(string campos, string tabla)
		{
			try
			{
				return EjecutarSelectDs(campos,tabla,"");
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
		public DataSet EjecutarSelectDs(string campos, string tabla, string filtro)
		{
			string sql	= "";
			DataSet r	= new DataSet();

			if(filtro=="")
				sql = string.Format("Select {0} from {1}", campos, tabla);
			else
				sql = string.Format("Select {0} from {1} where {2}", campos, tabla, filtro);

			try
			{
				
                r = (DataSet)EjecutaSqlSegunBD(sql, enmTipoRetornoEjecucion.DataSet);
				return r;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
        public object EjecutarSelectReaderMySQL(string campos, string tabla, string filtro)
        {
            string sql = "";
            object r ;

            if (filtro == "")
                sql = string.Format("Select {0} from {1}", campos, tabla);
            else
                sql = string.Format("Select {0} from {1} where {2}", campos, tabla, filtro);

            try
            {

                r = (object)EjecutaSqlSegunBD(sql, enmTipoRetornoEjecucion.Reader);
                return r;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public DataSet EjecutarSelectDsOrdenada(string campos, string tabla, string filtro)
        {
            string sql = "";
            DataSet r = new DataSet();

            if (filtro == "")
                sql = string.Format("Select {0} from {1} order by {0}", campos, tabla);
            else
                sql = string.Format("Select {0} from {1} where {2} order by {0}", campos, tabla, filtro);

            try
            {
                r = (DataSet)EjecutaSqlSegunBD(sql, enmTipoRetornoEjecucion.DataSet);
                return r;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
		
		public object EjecutarSelectScalar(string campos, string tabla)
		{
			try
			{
				return EjecutarSelectScalar(campos,tabla,"");
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
		public object EjecutarSelectScalar()
		{
			try
			{
				return mTipoBD;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}
		public object EjecutarSelectScalar(string campos, string tabla, string filtro)
		{
			string sql	= "";
			object r	= null;

			if(filtro=="")
				sql = string.Format("Select {0} from {1}", campos, tabla);
			else
				sql = string.Format("Select {0} from {1} where {2}", campos, tabla, filtro);

			try
			{
				r = EjecutaSqlSegunBD(sql, enmTipoRetornoEjecucion.Scalar);
				return r;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}

		#endregion

		#region < METODOS PUBLICOS INSERT >
		public int EjecutarInsert(string tabla, params CampoValor[] datos)
		{
			string	sql		= "";
			string	campos	= "";
			string	valores	= "";
			int		r=0;

			if(datos.Length==0) throw new ArgumentNullException("Especifique los Datos de la Instruccion INSERT");

			foreach(CampoValor cv in datos)
			{
				campos	+= cv.Campo + ",";
				valores	+= cv.Valor + ",";
			}
			campos	= EliminaUltimoCaracter(campos);
			valores = EliminaUltimoCaracter(valores);

			sql = string.Format("Insert Into {0} ({1}) VALUES ({2})",tabla,campos,valores);

			try
			{
				r = (int)EjecutaSqlSegunBD(sql,enmTipoRetornoEjecucion.NonQuery);
				return r;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}

		#endregion		

		#region < METODOS PUBLICOS UPDATE >
		public int EjecutarUpdate(string tabla, params CampoValor[] datos)
		{
			try
			{
				return EjecutarUpdate(tabla,"",datos);
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}

		public int EjecutarUpdate(string tabla, string filtro, params CampoValor[] datos)
		{
			string	sql				= "";
			string	asignaciones	= "";
			int		r=0;

			if(datos.Length==0) throw new ArgumentNullException("Especifique los Datos de la Instruccion UPDATE");

			foreach(CampoValor cv in datos)
			{
				asignaciones	+= cv.Campo + "=" + cv.Valor + ",";
			}
			asignaciones = EliminaUltimoCaracter(asignaciones);

			if(filtro=="")
				sql = string.Format("UPDATE {0} SET {1}",tabla,asignaciones);
			else
				sql = string.Format("UPDATE {0} SET {1} WHERE {2}",tabla,asignaciones,filtro);

			try
			{
				r = (int)EjecutaSqlSegunBD(sql, enmTipoRetornoEjecucion.NonQuery);
				return r;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}

		#endregion		

		#region < METODOS PUBLICOS DELETE >
		public int EjecutarDelete(string tabla)
		{
			try
			{
				return EjecutarDelete(tabla,"");
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}

		public int EjecutarDelete(string tabla, string filtro)
		{
			string	sql				= "";
			int		r=0;

			if(filtro=="")
				sql = string.Format("DELETE FROM {0}",tabla);
			else
				sql = string.Format("DELETE FROM {0} WHERE {1}",tabla,filtro);

			try
			{
				r = (int)EjecutaSqlSegunBD(sql, enmTipoRetornoEjecucion.NonQuery);
				return r;
			}
			catch(Exception ex)
			{
				throw ex;
			}
		}


		#endregion

		#region < METODOS PUBLICOS STORED PROCEDURES >
		public int EjecutarProcedimiento(string nombre, params object[] parametros)
		{
			int r=0;
			try
			{
				r = (int)EjecutaProcedimientoSegunBD(nombre,parametros,enmTipoRetornoEjecucion.NonQuery);
			}
			catch(Exception ex)
			{
				throw ex;
			}
			return r;
		}
        public int EjecutarProcedimientoMySQL(string nombre, params MySqlParameter[] parametros)
        {
            int r = 0;
            try
            {
                r = (int)EjecutaProcedimientoSegunBDMYSQL(nombre, parametros, enmTipoRetornoEjecucion.NonQuery);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return r;
        }
        public int EjecutarProcedimientoMySQL(string sentenciaMySqL)
        {
            int r = 0;
            try
            {
                r = (int)EjecutaProcedimientoSegunBDMySQL(sentenciaMySqL, enmTipoRetornoEjecucion.NonQuery);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return r;
        }
        
		#endregion

	}

	public enum enmTipoBaseDatos
	{
        SQL,
        MySQL,
		Oracle,
		OleDB
	}
	public enum enmTipoRetornoEjecucion
	{
		DataSet,
		NonQuery,
		Reader,
		Scalar
	}
}
